from core import KeyValueStorage, Config, Logger
from pydantic import BaseModel
from typing import Optional, Union, Type, TypeVar

T = TypeVar('T', bound=BaseModel)

class DataAccess:

    store: KeyValueStorage = None    
    def __init__(self):
        self.store = KeyValueStorage()

    def close(self):
        """
        关闭存储连接。

        该方法关闭对象所关联的存储连接。调用此方法后，存储应该处于关闭状态，不可进行读写操作。

        参数:
        self - 对象自身的引用。

        返回值:
        无
        """
        self.store.close()  # 关闭存储连接
    
    def generate_redis_key(cls: Type, unique_identifier: Optional[str]="SGLN") -> str: 
        """
        生成用于Redis的唯一键。
    
        参数:
        - cls: 类型，表示生成键名所基于的类。
        - unique_identifier: 字符串，用于生成键的唯一标识符，默认为"SGLN"。SGLN 代表单例singleton
        
        返回值:
        - 字符串，格式为"<类名>:<唯一标识符>"。
        """ 
        return f'{cls.__name__}:{unique_identifier}'  

    def save_data(self, obj :BaseModel, unique_identifier: Optional[str]="SGLN") -> bool:
        """
        保存数据到Redis。
        
        参数:
        - obj: BaseModel的实例，需要保存的对象。
        - unique_identifier: 字符串，用于生成唯一标识符的前缀，默认为"SGLN"。
        
        返回值:
        - 无
        """
        if obj is None:
            # 如果需要保存的对象为None，则记录一条调试信息并返回
            Logger.debug("Nothing need to save")
            return False
        # 生成Redis键
        key = self.generate_redis_key(obj, unique_identifier)
        # 将对象转换为JSON格式
        json = obj.model_dump_json()
        # 将JSON数据保存到Redis
        self.store.set(key, json)
        return True

    def load_data(self, cls: Type[T], unique_identifier: Optional[str]="SGLN") -> Union[T|None]:
        """
        从存储中加载数据。
        
        参数:
        - cls: 数据的类类型，用于后续的对象创建。
        - unique_identifier: 数据的唯一标识符，默认为"SGLN"。
        
        返回值:
        - 如果找到对应的存储数据，将其转换为cls类型后返回；否则返回None。
        """
        key = self.generate_redis_key(cls, unique_identifier)  # 生成Redis键
        if self.store.exists(key):  # 检查存储中是否存在该键
            json = self.store.get(key)  # 获取键对应的JSON数据
            return cls.model_validate_json(json)  # 使用cls的model_validate_json方法验证并返回数据
    
    def remove_data(self, cls: Type[T], unique_identifier: Optional[str]="SGLN") -> bool:
        """
        从存储中移除数据。
        
        参数:
        - cls: 数据的类类型，用于后续的对象创建。
        - unique_identifier: 数据的唯一标识符，默认为"SGLN"。
        
        返回值:
        - 如果找到对应的存储数据并成功移除，返回True；否则返回False。)
        """
        key = self.generate_redis_key(cls, unique_identifier)  # 生成Redis键
        if self.store.exists(key):  # 检查存储中是否存在该键
            self.store.delete(key)  # 删除键对应的数据
            return True
        else:
            return False
def create_db() -> DataAccess:
    """
    创建数据库访问对象。
    
    该函数不接受任何参数。
    
    返回值:
       返回一个DataAccess类型的实例，该实例可用于数据库的读写操作。
    """
    return DataAccess()